package com.tpfinal.agenda.view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import javax.swing.DefaultComboBoxModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.EmptyBorder;
import javax.swing.text.MaskFormatter;

import com.asynccommand.framework.ICommandListener;
import com.tpfinal.agenda.controller.MainController;
import com.tpfinal.agenda.core.AgendaActionsIDs;
import com.tpfinal.agenda.model.City;
import com.tpfinal.agenda.model.Company;
import com.tpfinal.agenda.model.Contact;
import com.tpfinal.agenda.model.Person;

public class ContactForm extends JFrame implements ICommandListener {

	private static final long serialVersionUID = 1L;

	private static ContactForm instance = null;

	private JPanel contentPane;
	private JTextField txtName;
	private JTextField txtAddress;
	private JTextField txtPhone;
	private JTextField txtEmail;
	private JTextField txtCellPhone;
	private JTextField txtWeb;
	private JTextField txtItem;

	private JComboBox<String> cboContactType;

	private JLabel lblName;

	private JFormattedTextField txtBirthDay;

	private JLabel lblWeb;

	private JLabel lblItem;

	private JButton btnAdd;

	private Contact selectedContact = null;

	private MainController controller;

	private JComboBox<City> cboCities;
	private JTextField txtLocalidad;
	private JTextField txtProvincia;

	private JLabel lblCellPhone;

	private JLabel lblBirthDay;

	/**
	 * Singleton para crear ContactForm()
	 */
	public static ContactForm getInstance() {
		if (instance == null) {
			instance = new ContactForm();
		}
		return instance;
	}

	public static void setInstanceNull() {
		instance = null;
	}

	/**
	 * Create the frame.
	 */

	private ContactForm() {
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosed(WindowEvent arg0) {
				ContactForm.setInstanceNull();
			}
		});
		controller = MainController.get();
		selectedContact = controller.getSelectedContact();
		// Registro el Form como observer de las Requests.
		controller.register(this);

		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(100, 100, 786, 288);
		setTitle("Sistema de gestion de contactos - Agregar Contacto");
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);

		JLabel lblContactData = new JLabel("Datos del Contacto:");

		JLabel lblContactType = new JLabel("Tipo de Contacto:");

		cboContactType = new JComboBox<String>();

		cboContactType.setModel(new DefaultComboBoxModel<String>(new String[] {
				"Empresa", "Persona" }));

		lblName = new JLabel("Nombre/Raz\u00F3n social:");

		txtName = new JTextField();
		txtName.setEnabled(false);
		txtName.setColumns(10);

		JLabel lblAddress = new JLabel("Direcci\u00F3n:");

		txtAddress = new JTextField();
		txtAddress.setEnabled(false);
		txtAddress.setColumns(10);

		JLabel lblZip = new JLabel("C\u00F3digo Postal:");

		JLabel lblPhone = new JLabel("Tel:");

		txtPhone = new JTextField();
		txtPhone.setEnabled(false);
		txtPhone.setColumns(10);

		JLabel lblEmail = new JLabel("Email:");

		txtEmail = new JTextField();
		txtEmail.setEnabled(false);
		txtEmail.setColumns(10);

		lblCellPhone = new JLabel("M\u00F3vil:");

		txtCellPhone = new JTextField();
		txtCellPhone.setEnabled(false);
		txtCellPhone.setColumns(10);

		lblBirthDay = new JLabel("Fecha de nac.:");

		/*
		 * Formatea campo para ingresar fecha
		 */
		MaskFormatter mascara = null;
		try {
			mascara = new MaskFormatter("##/##/####");
		} catch (ParseException ex) {

		}
		txtBirthDay = new JFormattedTextField(mascara);
		txtBirthDay.setEnabled(false);
		try {
			txtBirthDay.commitEdit();
		} catch (ParseException ex1) {
		}

		lblWeb = new JLabel("Web:");

		txtWeb = new JTextField();
		txtWeb.setEnabled(false);
		txtWeb.setColumns(10);

		btnAdd = new JButton("Agregar");
		btnAdd.setEnabled(false);
		btnAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				validateForm();
			}
		});

		lblItem = new JLabel("Rubro:");

		txtItem = new JTextField();
		txtItem.setEnabled(false);
		txtItem.setColumns(10);

		cboContactType.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				updateView(cboContactType.getSelectedIndex() == 1);
			}
		});

		JButton btnCancel = new JButton("Cancelar");
		btnCancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				dispose();
			}
		});

		cboCities = new JComboBox<City>();
		for (City ci : controller.getCitiesList()) {
			cboCities.addItem(ci);
		}

		cboCities.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				onCboCitiesChanged();
			}
		});

		JLabel lblLocalidad = new JLabel("Localidad:");

		JLabel lblProvincia = new JLabel("Provincia:");

		txtLocalidad = new JTextField();
		txtLocalidad.setEnabled(false);
		txtLocalidad.setColumns(10);

		txtProvincia = new JTextField();
		txtProvincia.setEnabled(false);
		txtProvincia.setColumns(10);

		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane
				.setHorizontalGroup(gl_contentPane
						.createParallelGroup(Alignment.LEADING)
						.addGroup(
								gl_contentPane
										.createSequentialGroup()
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.LEADING)
														.addComponent(
																lblContactData)
														.addGroup(
																gl_contentPane
																		.createSequentialGroup()
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.LEADING)
																						.addComponent(
																								lblName)
																						.addComponent(
																								lblContactType)
																						.addComponent(
																								lblAddress)
																						.addComponent(
																								lblPhone)
																						.addComponent(
																								lblCellPhone)
																						.addComponent(
																								lblWeb))
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.LEADING)
																						.addGroup(
																								gl_contentPane
																										.createSequentialGroup()
																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addGroup(
																												gl_contentPane
																														.createParallelGroup(
																																Alignment.TRAILING)
																														.addGroup(
																																gl_contentPane
																																		.createParallelGroup(
																																				Alignment.LEADING)
																																		.addGroup(
																																				gl_contentPane
																																						.createSequentialGroup()
																																						.addComponent(
																																								txtAddress,
																																								GroupLayout.PREFERRED_SIZE,
																																								GroupLayout.DEFAULT_SIZE,
																																								GroupLayout.PREFERRED_SIZE)
																																						.addPreferredGap(
																																								ComponentPlacement.RELATED)

																																						.addComponent(
																																								lblZip)
																																						.addPreferredGap(
																																								ComponentPlacement.UNRELATED)
																																						.addComponent(
																																								cboCities,
																																								GroupLayout.PREFERRED_SIZE,
																																								77,
																																								GroupLayout.PREFERRED_SIZE)
																																						.addPreferredGap(
																																								ComponentPlacement.UNRELATED)

																																		)
																																		.addGroup(
																																				gl_contentPane
																																						.createSequentialGroup()
																																						.addComponent(
																																								txtName,
																																								GroupLayout.PREFERRED_SIZE,
																																								GroupLayout.DEFAULT_SIZE,
																																								GroupLayout.PREFERRED_SIZE)
																																						.addPreferredGap(
																																								ComponentPlacement.UNRELATED)
																																						.addComponent(
																																								lblBirthDay)
																																						.addPreferredGap(
																																								ComponentPlacement.UNRELATED)
																																						.addComponent(
																																								txtBirthDay,
																																								GroupLayout.PREFERRED_SIZE,
																																								69,
																																								GroupLayout.PREFERRED_SIZE))
																																		.addGroup(
																																				gl_contentPane
																																						.createSequentialGroup()
																																						.addGroup(
																																								gl_contentPane
																																										.createParallelGroup(
																																												Alignment.LEADING)
																																										.addComponent(
																																												txtWeb,
																																												GroupLayout.PREFERRED_SIZE,
																																												GroupLayout.DEFAULT_SIZE,
																																												GroupLayout.PREFERRED_SIZE)
																																										.addComponent(
																																												txtPhone,
																																												GroupLayout.PREFERRED_SIZE,
																																												GroupLayout.DEFAULT_SIZE,
																																												GroupLayout.PREFERRED_SIZE))
																																						.addPreferredGap(
																																								ComponentPlacement.UNRELATED)
																																						.addGroup(
																																								gl_contentPane
																																										.createParallelGroup(
																																												Alignment.LEADING,
																																												false)
																																										.addComponent(
																																												lblItem)
																																										.addGroup(
																																												gl_contentPane
																																														.createSequentialGroup()
																																														.addGap(5)
																																														.addComponent(
																																																lblEmail)))
																																						.addPreferredGap(
																																								ComponentPlacement.UNRELATED)
																																						.addGroup(
																																								gl_contentPane
																																										.createParallelGroup(
																																												Alignment.LEADING)
																																										.addComponent(
																																												txtItem,
																																												GroupLayout.PREFERRED_SIZE,
																																												GroupLayout.DEFAULT_SIZE,
																																												GroupLayout.PREFERRED_SIZE)
																																										.addComponent(
																																												txtEmail,
																																												GroupLayout.PREFERRED_SIZE,
																																												GroupLayout.DEFAULT_SIZE,
																																												GroupLayout.PREFERRED_SIZE)))
																																		.addComponent(
																																				txtCellPhone,
																																				GroupLayout.PREFERRED_SIZE,
																																				GroupLayout.DEFAULT_SIZE,
																																				GroupLayout.PREFERRED_SIZE))
																														.addGroup(
																																gl_contentPane
																																		.createSequentialGroup()
																																		.addComponent(
																																				btnCancel)
																																		.addPreferredGap(
																																				ComponentPlacement.UNRELATED)
																																		.addComponent(
																																				btnAdd)))
																										.addPreferredGap(
																												ComponentPlacement.RELATED)

																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addComponent(
																												lblLocalidad)
																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addComponent(
																												txtLocalidad,
																												GroupLayout.PREFERRED_SIZE,
																												GroupLayout.DEFAULT_SIZE,
																												GroupLayout.PREFERRED_SIZE)
																										.addGap(11)
																										.addComponent(
																												lblProvincia)
																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addComponent(
																												txtProvincia,
																												GroupLayout.PREFERRED_SIZE,
																												GroupLayout.DEFAULT_SIZE,
																												GroupLayout.PREFERRED_SIZE))
																						.addGroup(
																								gl_contentPane
																										.createSequentialGroup()
																										.addGap(18)
																										.addComponent(
																												cboContactType,
																												GroupLayout.PREFERRED_SIZE,
																												GroupLayout.DEFAULT_SIZE,
																												GroupLayout.PREFERRED_SIZE)))))
										.addContainerGap(22, Short.MAX_VALUE)));
		gl_contentPane
				.setVerticalGroup(gl_contentPane
						.createParallelGroup(Alignment.LEADING)
						.addGroup(
								gl_contentPane
										.createSequentialGroup()
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.TRAILING)
														.addComponent(
																cboCities,
																GroupLayout.PREFERRED_SIZE,
																GroupLayout.DEFAULT_SIZE,
																GroupLayout.PREFERRED_SIZE)
														.addGroup(
																gl_contentPane
																		.createSequentialGroup()
																		.addComponent(
																				lblContactData)
																		.addGap(18)
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.BASELINE)
																						.addComponent(
																								lblContactType)
																						.addComponent(
																								cboContactType,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE))
																		.addPreferredGap(
																				ComponentPlacement.UNRELATED)
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.BASELINE)
																						.addComponent(
																								lblName)
																						.addComponent(
																								txtName,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE)
																						.addComponent(
																								lblBirthDay)
																						.addComponent(
																								txtBirthDay,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE))
																		.addPreferredGap(
																				ComponentPlacement.RELATED)
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.TRAILING)
																						.addComponent(
																								lblAddress)
																						.addComponent(
																								txtAddress,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE)
																						.addGroup(
																								gl_contentPane
																										.createParallelGroup(
																												Alignment.BASELINE)
																										.addComponent(
																												lblZip)
																										.addComponent(
																												lblLocalidad)
																										.addComponent(
																												lblProvincia)
																										.addComponent(
																												txtLocalidad,
																												GroupLayout.PREFERRED_SIZE,
																												GroupLayout.DEFAULT_SIZE,
																												GroupLayout.PREFERRED_SIZE)
																										.addComponent(
																												txtProvincia,
																												GroupLayout.PREFERRED_SIZE,
																												GroupLayout.DEFAULT_SIZE,
																												GroupLayout.PREFERRED_SIZE)))))
										.addPreferredGap(
												ComponentPlacement.RELATED)
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.TRAILING)
														.addGroup(
																gl_contentPane
																		.createSequentialGroup()
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.TRAILING)
																						.addComponent(
																								lblPhone)
																						.addComponent(
																								txtPhone,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE))
																		.addPreferredGap(
																				ComponentPlacement.RELATED)
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.BASELINE)
																						.addComponent(
																								lblCellPhone)
																						.addComponent(
																								txtCellPhone,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE))
																		.addPreferredGap(
																				ComponentPlacement.RELATED)
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.BASELINE)
																						.addComponent(
																								lblWeb)
																						.addComponent(
																								txtWeb,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE)))
														.addGroup(
																gl_contentPane
																		.createSequentialGroup()
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.BASELINE)
																						.addComponent(
																								lblEmail)
																						.addComponent(
																								txtEmail,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE))
																		.addGap(32)
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.BASELINE)
																						.addComponent(
																								lblItem)
																						.addComponent(
																								txtItem,
																								GroupLayout.PREFERRED_SIZE,
																								GroupLayout.DEFAULT_SIZE,
																								GroupLayout.PREFERRED_SIZE))))
										.addGap(18)
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.BASELINE)
														.addComponent(btnAdd)
														.addComponent(btnCancel))
										.addContainerGap(12, Short.MAX_VALUE)));
		contentPane.setLayout(gl_contentPane);
	}

	protected void validateForm() {

		if ((txtName.getText().length() == 0
				|| txtAddress.getText().length() == 0
				|| txtPhone.getText().length() == 0
				|| (txtCellPhone.isVisible() && txtCellPhone.getText().length() == 0)
				|| txtEmail.getText().length() == 0
				|| (txtWeb.isVisible() && txtWeb.getText().length() == 0) || (txtItem
				.isVisible() && txtItem.getText().length() == 0))) {
			JOptionPane
					.showMessageDialog(null,
							"No complet� todos los campos obligatorios",
							"Validaci�n de datos ingresados",
							JOptionPane.ERROR_MESSAGE);
		} else if ((!txtPhone.getText().matches("[0-9]+"))
				|| (!txtEmail.getText().matches(
						"[a-zA-Z0-9.]+@[a-zA-Z0-9.]+.[a-zA-z0-9.]+"))
				|| (txtCellPhone.isVisible() && !txtCellPhone.getText()
						.matches("[0-9]+"))
				|| (txtItem.isVisible() && !txtItem.getText().matches(
						"[a-zA-Z0-9]+"))
				|| (txtWeb.isVisible() && !txtWeb
						.getText()
						.matches(
								"(http://|https://|ftp://|file://)?[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"))) {
			JOptionPane
					.showMessageDialog(null,
							"Los datos ingresados no son correctos",
							"Validaci�n de datos ingresados",
							JOptionPane.ERROR_MESSAGE);
		} else {
			updateContact();
		}
	}

	public void updateView(boolean asPerson) {
		txtName.setEnabled(true);
		txtAddress.setEnabled(true);
		txtPhone.setEnabled(true);
		txtEmail.setEnabled(true);
		btnAdd.setEnabled(true);
		lblWeb.setVisible(!asPerson);
		txtWeb.setVisible(!asPerson);
		txtWeb.setEnabled(!asPerson);
		lblItem.setVisible(!asPerson);
		txtItem.setEnabled(!asPerson);
		txtItem.setVisible(!asPerson);
		lblCellPhone.setVisible(asPerson);
		txtCellPhone.setVisible(asPerson);
		txtCellPhone.setEnabled(asPerson);
		lblBirthDay.setVisible(asPerson);
		txtBirthDay.setVisible(asPerson);
		txtBirthDay.setEnabled(asPerson);
		lblName.setText((asPerson) ? "Nombre:" : "Razon Social");
	}

	public void renderContactInfo() {
		txtName.setText(selectedContact.getName());
		txtAddress.setText(selectedContact.getAddress());
		txtPhone.setText(String.valueOf(selectedContact.getPhone()));
		txtEmail.setText(selectedContact.getEmail());
		btnAdd.setText("Modificar");
		cboCities.setSelectedItem(selectedContact.getCityInfo());

		if (selectedContact instanceof Person) {

			cboContactType.setSelectedIndex(1);

			txtCellPhone.setText(String.valueOf(((Person) selectedContact)
					.getCellphone()));

			Date birth = ((Person) selectedContact).getBirthday();
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
			String fecha;
			if (birth == null) {
				fecha = "  /  /    ";
			} else {
				fecha = sdf.format(birth);
			}

			txtBirthDay.setText(fecha);

		}

		if (selectedContact instanceof Company) {

			cboContactType.setSelectedIndex(0);
			txtWeb.setText(((Company) selectedContact).getUrl());
			txtItem.setText(((Company) selectedContact).getBusinessSector());

		}
	}

	public void start() {
		updateView(selectedContact instanceof Person);
		if (selectedContact != null) {
			setTitle("Sistema de gestion de contactos - Modificar Contacto");
			renderContactInfo();
		}
		setVisible(true);
	}

	public void updateContact() {
		int id = 0;
		if (selectedContact != null) {
			id = selectedContact.getId();
		}
		String name = txtName.getText();
		String address = txtAddress.getText();
		int phone = Integer.parseInt(txtPhone.getText());
		String email = txtEmail.getText();

		City cityInfo = (City) cboCities.getSelectedItem();

		Contact updatingContact;

		if (cboContactType.getSelectedIndex() == 1) {

			String birthday = txtBirthDay.getText();
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
			Date d = null;
			try {
				d = sdf.parse(birthday);
			} catch (ParseException e) {
				e.printStackTrace();
			}
			int cellphone = Integer.parseInt(txtCellPhone.getText());

			updatingContact = new Person(id, name, address, phone, email, d,
					cellphone, cityInfo);

		} else {

			String url = txtWeb.getText();
			String businessSector = txtItem.getText();

			updatingContact = new Company(id, name, address, phone, email, url,
					businessSector, cityInfo);

		}

		if (selectedContact != null) {
			controller.updateContact(updatingContact);
		} else {
			controller.addContact(updatingContact);
		}

	}

	@Override
	public void onDone(int actionID, Map<String, Object> params) {
		switch (actionID) {
		case AgendaActionsIDs.UPDATE_CONTACT:
		case AgendaActionsIDs.INSTERT_CONTACT:
			dispose();
			break;

		default:
			break;
		}
	}

	@Override
	public void onProgress(int actionID, Map<String, Object> params) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onError(int actionID, Map<String, Object> params) {
		// TODO Auto-generated method stub

	}

	private void onCboCitiesChanged() {
		City selected = (City) cboCities.getSelectedItem();
		txtProvincia.setText(selected.getState());
		txtLocalidad.setText(selected.getCity());
	}
}
